﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WorldBankBBS.Translators
{
    public static class TextWrapper
    {
        public static string WrapText(this string sourceText, int width)
        {
            var s = new StringBuilder();
            var w = width;
            var p = 0;

            foreach (var word in sourceText.Split(new[] { ' ' }))
            {
                if (word.Length + p < w)
                {
                    s.Append(' ' + word);
                    p += word.Length + 1;
                }
                else
                {
                    s.Append("\n" + word);
                    p = word.Length;
                }
            }

            return s.ToString();
        }

        public static byte[] WrapText(this byte[] sourceText, string encoding, int width)
        {
            return sourceText.WrapText(0, sourceText.Length, encoding, width);
        }

        public static byte[] WrapText(this byte[] sourceText, int position, int length, string encoding, int width)
        {
            var l = new List<List<byte>>();
            var t = new List<byte>();
            var w = width;
            var p = 0;
            var a = false;

            byte last = 0;
            for (int i = 0; i < length; ++i)
            {
                var b = sourceText[position + i];
                if (b == 0) break;
                if ((b == '\n' && last != 13) || (b == 13 && last != '\n'))
                {
                    t.Add(b);
                    l.Add(t);
                    t = new List<byte>();
                    p = 0;
                }
                else if (b == 13)
                {
                    t.Add(b);
                    ++p;
                }
                else if (b == ' ')
                {
                    l.Add(t);
                    if (p < w)
                    {
                        t.Add(b);
                        ++p;
                    }
                    else
                    {
                        p = 0;
                    }
                    t = new List<byte>();
                }
                else if (b == 27)
                {
                    a = true;
                    t.Add(b);
                }
                else
                {
                    t.Add(b);
                    if (p < w - 1 || t.Count >= w)
                    {
                        if (encoding == "PETSCII")
                        {
                            if ((b >= 0x21 && b <= 0xff)) ++p;
                            else
                                Trace.WriteLine(string.Format("Skipping [{0}]", b));
                        }
                        else if (encoding == "ANSI")
                        {
                            if (a && 
                                ((b >= 'a' && b <= 'z') || 
                                    (b >= 'A' && b <= 'Z')))
                            {
                                a = false;
                                --p;
                            }

                            if (!a) ++p;
                        }
                        else
                        {
                            ++p;
                        }
                    }
                    else
                    {
                        if (encoding == "PETSCII")
                        {
                            t.Insert(0, (byte)13);
                        }
                        else
                        {
                            t.Insert(0, (byte)'\r');
                            t.Insert(1, (byte)'\n');
                        }
                        p = t.Count;
                    }
                }
                last = b;
            }

            if (t.Count > 0) l.Add(t);

            var count = 0;
            foreach (var tt in l)
            {
                count += tt.Count;
            }

            var result = new byte[count];

            var ii = 0;
            foreach (var tt in l)
            {
                foreach (var b in tt)
                {
                    result[ii++] = b;
                }
            }

            return result;
        }
    }
}
